<script setup lang="ts">
import type { LowcodeGroovyApi } from '#/api/lowcode/groovy';

import { ref, watch, nextTick } from 'vue';

import { Icon } from '@iconify/vue';
import { VueMonacoEditor } from '@guolao/vue-monaco-editor';

interface Props {
  value?: string;
  scriptInfo?: LowcodeGroovyApi.GroovyScript;
  readonly?: boolean;
  height?: number | string;
}

interface Emits {
  (e: 'update:value', value: string): void;
  (e: 'save', value: string): void;
  (e: 'execute', value: string): void;
}

const props = withDefaults(defineProps<Props>(), {
  value: '',
  readonly: false,
  height: '500px',
});
const emit = defineEmits<Emits>();

// Monaco Editor引用
const monacoEditorRef = ref();
const saving = ref(false);
const executing = ref(false);
const showSettings = ref(false);

// 编辑器设置
const editorTheme = ref<'vs-dark' | 'vs' | 'hc-black'>('vs-dark');
const fontSize = ref(14);
const tabSize = ref(2);
const wordWrap = ref(true);
const showLineNumbers = ref(true);
const minimap = ref(false);

const cursorPosition = ref({ line: 1, column: 1 });

// 处理内容变化
const handleChange = (value: string) => {
  emit('update:value', value);
};

// Monaco Editor挂载事件
const handleEditorMount = (editor: any, monaco: any) => {
  // 等待字体加载完成再进行初始化，避免光标位置错位
  document.fonts.ready.then(() => {
    // 重新测量字体以确保光标位置准确
    monaco.editor.remeasureFonts();
  });

  // 配置Groovy语言支持 - 基于Java语法扩展
  monaco.languages.register({ id: 'groovy' });

  // 定义Groovy语法高亮规则
  monaco.languages.setMonarchTokensProvider('groovy', {
    tokenizer: {
      root: [
        // Groovy关键字
        [/\b(def|class|interface|package|import|extends|implements|as|in|new|return|if|else|for|while|do|switch|case|default|break|continue|try|catch|finally|throw|throws|public|private|protected|static|final|abstract|synchronized|native|strictfp|transient|volatile|assert|enum|this|super|null|true|false)\b/, 'keyword'],
        
        // Groovy特有关键字
        [/\b(it|owner|delegate|thisObject)\b/, 'keyword.groovy'],
        
        // 数字
        [/\d*\.\d+([eE][\-+]?\d+)?[fFdD]?/, 'number.float'],
        [/0[xX][0-9a-fA-F]+[Ll]?/, 'number.hex'],
        [/0[0-7]+[Ll]?/, 'number.octal'],
        [/\d+[lL]?/, 'number'],
        
        // 字符串
        [/"([^"\\]|\\.)*"/, 'string'],
        [/'([^'\\]|\\.)*'/, 'string'],
        [/"""/, 'string', '@multilinestring'],
        [/'''/, 'string', '@multilinevstring'],
        
        // GString
        [/\$"/, 'string.gstring', '@gstring'],
        [/\$\//, 'string.gstring', '@gstringslash'],
        
        // 注释
        [/\/\*/, 'comment', '@comment'],
        [/\/\/.*$/, 'comment'],
        
        // 操作符
        [/[{}()\[\]]/, '@brackets'],
        [/[<>](?!@symbols)/, '@brackets'],
        [/@symbols/, 'delimiter'],
        
        // 标识符
        [/[a-zA-Z_$][a-zA-Z0-9_$]*/, 'identifier'],
      ],
      
      comment: [
        [/[^\/*]+/, 'comment'],
        [/\*\//, 'comment', '@pop'],
        [/[\/*]/, 'comment']
      ],
      
      multilinestring: [
        [/[^"]+/, 'string'],
        [/"""/, 'string', '@pop'],
        [/"/, 'string']
      ],
      
      multilinevstring: [
        [/[^']+/, 'string'],
        [/'''/, 'string', '@pop'],
        [/'/, 'string']
      ],
      
      gstring: [
        [/[^"$]+/, 'string'],
        [/\$\{/, 'string.gstring', '@gstringexpr'],
        [/\$[a-zA-Z_$][a-zA-Z0-9_$]*/, 'variable'],
        [/"/, 'string', '@pop']
      ],
      
      gstringexpr: [
        [/[^}]+/, 'identifier'],
        [/\}/, 'string.gstring', '@pop']
      ],
      
      gstringslash: [
        [/[^\/]+/, 'string'],
        [/\//, 'string', '@pop']
      ]
    },
    
    symbols: /[=><!~?:&|+\-*\/\^%]+/,
    brackets: [
      { open: '{', close: '}', token: 'delimiter.curly' },
      { open: '[', close: ']', token: 'delimiter.square' },
      { open: '(', close: ')', token: 'delimiter.parenthesis' }
    ]
  });

  // 禁用JavaScript的语法检查以减少误报
  monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: true,
    noSyntaxValidation: true,
    noSuggestionDiagnostics: true
  });

  // 设置编辑器使用Groovy语言
  const model = editor.getModel();
  if (model) {
    monaco.editor.setModelLanguage(model, 'groovy');
  }

  // 添加快捷键
  editor.addAction({
    id: 'save-script',
    label: '保存脚本',
    keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS],
    run: () => handleSave(),
  });

  editor.addAction({
    id: 'execute-script',
    label: '执行脚本',
    keybindings: [monaco.KeyCode.F5],
    run: () => handleExecute(),
  });

  editor.addAction({
    id: 'format-script',
    label: '格式化脚本',
    keybindings: [monaco.KeyMod.Shift | monaco.KeyMod.Alt | monaco.KeyCode.KeyF],
    run: () => handleFormat(),
  });

  // 监听光标位置变化
  editor.onDidChangeCursorPosition((e: any) => {
    cursorPosition.value = {
      line: e.position.lineNumber,
      column: e.position.column,
    };
  });

  // 额外的光标位置错位修复
  // 延迟触发重新测量，确保布局完成
  setTimeout(() => {
    monaco.editor.remeasureFonts();
    editor.layout();
  }, 100);

  // 监听DOM变化，当容器大小变化时重新布局
  const resizeObserver = new ResizeObserver(() => {
    editor.layout();
  });
  
  const editorElement = editor.getDomNode();
  if (editorElement) {
    resizeObserver.observe(editorElement.parentElement || editorElement);
  }
};

// 保存脚本
const handleSave = async () => {
  const value = props.value || '';
  saving.value = true;
  try {
    emit('save', value);
  } finally {
    saving.value = false;
  }
};

// 执行脚本
const handleExecute = async () => {
  const value = props.value || '';

  if (!value.trim()) {
    return;
  }

  if (value.length > 10_000) {
    return;
  }

  executing.value = true;
  try {
    emit('execute', value);
  } finally {
    executing.value = false;
  }
};

// 格式化代码
const handleFormat = async () => {
  const editor = monacoEditorRef.value?.getEditor();
  if (editor) {
    try {
      await editor.getAction('editor.action.formatDocument')?.run();
    } catch (error) {
      console.warn('Format action not available');
    }
  }
};

// 重置内容
const handleReset = () => {
  emit('update:value', props.value || '');
};

// 暴露编辑器实例方法
defineExpose({
  getValue: () => props.value || '',
  setValue: (value: string) => emit('update:value', value),
  focus: () => monacoEditorRef.value?.getEditor()?.focus(),
  format: handleFormat,
  getEditor: () => monacoEditorRef.value?.getEditor(),
});
</script>

<template>
  <div class="groovy-editor">
    <!-- 临时编辑器 -->
    <div
      class="editor-container"
      :style="{ height: typeof height === 'number' ? `${height}px` : height }"
    >
      <VueMonacoEditor
        ref="monacoEditorRef"
        v-model:value="props.value"
        language="groovy"
        :theme="editorTheme"
        :options="{
          fontSize: fontSize,
          tabSize: tabSize,
          wordWrap: wordWrap ? 'on' : 'off',
          lineNumbers: showLineNumbers ? 'on' : 'off',
          minimap: { enabled: minimap },
          readOnly: readonly,
          automaticLayout: true,
          scrollBeyondLastLine: false,
          // 修复光标位置错位问题的关键配置
          fontLigatures: false,  // 禁用字体连字符
          disableLayerHinting: false,  // 保持图层提示
          renderLineHighlight: 'all',  // 渲染行高亮
          cursorSmoothCaretAnimation: 'off',  // 禁用光标动画避免位置偏移
          scrollbar: {
            useShadows: false  // 禁用阴影可能有助于避免渲染问题
          }
        }"
        :height="typeof height === 'number' ? `${height}px` : height"
        @change="handleChange"
        @mount="handleEditorMount"
      />
    </div>

    <!-- 编辑器工具栏 -->
    <div class="editor-toolbar">
      <a-space>
        <a-button
          type="primary"
          size="small"
          :loading="saving"
          @click="handleSave"
        >
          <template #icon>
            <Icon icon="ant-design:save-outlined" />
          </template>
          保存 (Ctrl+S)
        </a-button>

        <a-button size="small" @click="handleFormat">
          <template #icon>
            <Icon icon="ant-design:format-painter-outlined" />
          </template>
          格式化 (Shift+Alt+F)
        </a-button>

        <a-divider type="vertical" />

        <a-button
          type="primary"
          ghost
          size="small"
          :loading="executing"
          @click="handleExecute"
        >
          <template #icon>
            <Icon icon="ant-design:play-circle-outlined" />
          </template>
          执行 (F5)
        </a-button>

        <a-button size="small" @click="handleReset">
          <template #icon>
            <Icon icon="ant-design:reload-outlined" />
          </template>
          重置
        </a-button>

        <a-button size="small" @click="showSettings = true">
          <template #icon>
            <Icon icon="ant-design:setting-outlined" />
          </template>
          设置
        </a-button>
      </a-space>

      <a-space class="ml-auto">
        <a-tag v-if="scriptInfo?.version" color="blue">
          v{{ scriptInfo.version }}
        </a-tag>
        <span class="text-sm text-gray-500">
          行: {{ cursorPosition.line }} 列: {{ cursorPosition.column }}
        </span>
      </a-space>
    </div>

    <!-- 设置弹窗 -->
    <a-modal
      v-model:open="showSettings"
      title="编辑器设置"
      width="500px"
      @ok="showSettings = false"
    >
      <a-form layout="vertical">
        <a-form-item label="编辑器主题">
          <a-select v-model:value="editorTheme" placeholder="选择主题">
            <a-select-option value="vs-dark">深色主题</a-select-option>
            <a-select-option value="vs">浅色主题</a-select-option>
            <a-select-option value="hc-black">高对比度</a-select-option>
          </a-select>
        </a-form-item>

        <a-form-item label="字体大小">
          <a-input-number
            v-model:value="fontSize"
            :min="12"
            :max="28"
            addon-after="px"
          />
        </a-form-item>

        <a-form-item label="Tab键宽度">
          <a-input-number v-model:value="tabSize" :min="2" :max="8" />
        </a-form-item>

        <a-row :gutter="16">
          <a-col :span="12">
            <a-form-item>
              <a-checkbox v-model:checked="wordWrap">
                自动换行
              </a-checkbox>
            </a-form-item>
          </a-col>
          <a-col :span="12">
            <a-form-item>
              <a-checkbox v-model:checked="showLineNumbers">显示行号</a-checkbox>
            </a-form-item>
          </a-col>
        </a-row>

        <a-form-item>
          <a-checkbox v-model:checked="minimap">显示小地图</a-checkbox>
        </a-form-item>

      </a-form>
    </a-modal>
  </div>
</template>

<style scoped>
.groovy-editor {
  @apply flex h-full flex-col;
}

.editor-container {
  @apply flex-1 rounded-t border border-gray-300;
}

/* Monaco Editor 容器样式 */
.editor-container :deep(.monaco-editor) {
  border-radius: 4px 4px 0 0;
}

/* 修复光标位置错位问题：避免使用 !important 强制覆盖字体，让Monaco Editor自己处理字体渲染 */
.editor-container :deep(.monaco-editor .view-lines) {
  font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', 'Cascadia Code', 'Roboto Mono', 'Courier New', monospace;
  /* 确保字体渲染的一致性 */
  font-variant-ligatures: none;
  /* 避免字母间距问题 */
  letter-spacing: 0;
}

/* 工具栏样式 */
.editor-toolbar {
  @apply flex items-center justify-between rounded-b border-t border-gray-300 bg-gray-50 p-2;
}

.editor-toolbar .ml-auto {
  margin-left: auto;
}

/* 深色主题时的工具栏调整 */
.groovy-editor.dark .editor-toolbar {
  @apply bg-gray-800 border-gray-600;
}

/* 响应式调整 */
@media (max-width: 768px) {
  .editor-toolbar {
    @apply flex-wrap gap-1 p-1;
  }

  .editor-toolbar .ant-space {
    @apply flex-wrap;
  }
}
</style>
